package cc.shacocloud.kotlin.tools.csv

import cc.shacocloud.kotlin.tools.json.Json

/**
 * CSV中一行的表示
 * @author 思追(shaco)
 */
class CsvRow(
    /** 原始行号  */
    private val originalLineNumber: Long,
    /** 标题Map */
    val headerMap: Map<String, Int> = emptyMap(),
    /** 数据字段 */
    private val fields: List<String>
) : List<String> {

    /**
     * 获取本行所有字段值列表
     *
     * @return 字段值列表
     */
    val rawFields: List<String> get() = fields

    /**
     * 获取标题与字段值对应的 Map
     *
     * @return 标题与字段值对应的 Map
     */
    val fieldMap: Map<String, String?>
        get() {
            val fieldMap = LinkedHashMap<String, String?>(headerMap.size, 1f)
            headerMap.forEach { (k, v) ->
                fieldMap[k] = v?.let { get(it) }
            }

            return fieldMap
        }

    /**
     * 获取字段格式
     *
     * @return 字段格式
     */
    val fieldCount: Int get() = fields.size

    /**
     * 获取标题对应的字段内容
     *
     * @param name 标题名
     * @return 字段值，null表示无此字段值
     * @throws IllegalStateException CSV文件无标题行抛出此异常
     */
    fun getByName(name: String): String? {
        val col = headerMap[name]
        if (col != null) {
            return get(col)
        }
        return null
    }

    /**
     * 一行数据转换为Bean对象
     *
     * @param <T> Bean类型
     * @param clazz bean类
     * @return Bean
     */
    fun <T> toBean(clazz: Class<T>): T {
        return Json.convertValue(fieldMap, clazz)
    }

    override val size: Int
        get() = fields.size

    override fun get(index: Int): String {
        return fields[index]
    }

    override fun indexOf(element: String): Int {
        return fields.indexOf(element)
    }

    override fun containsAll(elements: Collection<String>): Boolean {
        return fields.containsAll(elements)
    }

    override fun contains(element: String): Boolean {
        return fields.contains(element)
    }

    override fun isEmpty(): Boolean {
        return fields.isEmpty()
    }

    override fun iterator(): Iterator<String> {
        return fields.iterator()
    }

    override fun listIterator(): ListIterator<String> {
        return fields.listIterator()
    }

    override fun listIterator(index: Int): ListIterator<String> {
        return fields.listIterator(index)
    }

    override fun subList(fromIndex: Int, toIndex: Int): List<String> {
        return fields.subList(fromIndex, toIndex)
    }

    override fun lastIndexOf(element: String): Int {
        return fields.lastIndexOf(element)
    }

    override fun toString(): String {
        val sb = StringBuilder("CsvRow{")
        sb.append("originalLineNumber=")
        sb.append(originalLineNumber)
        sb.append(", ")

        sb.append("fields=")
        sb.append('{')
        val it = fieldMap.entries.iterator()
        while (it.hasNext()) {
            val entry = it.next()
            sb.append(entry.key)
            sb.append('=')
            if (entry.value != null) {
                sb.append(entry.value)
            }
            if (it.hasNext()) {
                sb.append(", ")
            }
        }
        sb.append('}')

        sb.append('}')
        return sb.toString()
    }
}
